package com.rgs.se.zookeeper.javaapi;

import com.google.common.base.Strings;
import org.apache.zookeeper.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;

/**
 * @author Ren Gaoshuai
 * @ClassName TestJavaApi
 * @Description zookeepeer 原生客户端
 * @date 2021-10-27 8:37
 **/
public class TestJavaApi {

    private final static String CONNECTION = "127.0.0.1:2181";

    private final static Integer TIME_OUT = 10000;

    private final static CountDownLatch countDownLatch = new CountDownLatch(1);

    private ZooKeeper zk;
    private static final Logger logger = LoggerFactory.getLogger(TestJavaApi.class);

    /**
     * 创建zookeeper连接（不保护情况）
     * 问题：有可能还没有连接就返回了
     * CONNECTING（连接中） CONNECTED（已连接）
     * RECONNECTING（重连中） RECONNECTED（重连成功）
     * CLOSE（关闭）
     */
    public ZooKeeper createConnection() throws IOException, InterruptedException {
        this.zk.close();
        return new ZooKeeper(CONNECTION,TIME_OUT,null);
    }

    /**
     * 获取zookeeper连接，
     */

    public ZooKeeper createSafeConnection() throws IOException, InterruptedException {
        ZooKeeper zooKeeper = new ZooKeeper(CONNECTION, TIME_OUT, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                //判断已连接的情况，释放主线程
                if (Objects.equals(watchedEvent.getState(),Event.KeeperState.SyncConnected)){
                    countDownLatch.countDown();
                }
            }
        });

        countDownLatch.await();
        zk = zooKeeper;
        System.out.println("成功创建zookeeper安全连接。。。当前状态为："+zooKeeper.getState());
        return zooKeeper;
    }

    /**
     * 关闭zookeeper连接
     */
    public void close(){
        if (Objects.nonNull(this.zk)){
            try {
                zk.close();
            } catch (InterruptedException e) {
                e.printStackTrace();
                logger.info("关闭zookeeper连接失败");
            }
        }
    }

    /**
     * 创建节点
     */
    public boolean createPath(String path,String data){
        //创建 临时节点 开放节点
        try {
            this.zk.create(path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 获取指定路径的数据
     * @param path
     * @return
     */
    public String getData(String path){
        try {
            return new String(this.zk.getData(path,false,null));
        } catch (KeeperException e) {
            e.printStackTrace();
            return "";
        } catch (InterruptedException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 更新指定路径的数据
     * @param path
     * @return
     */
    public boolean updateData(String path,String newData) {
        String oldData = this.getData(path);
        try {
            this.zk.setData(path, newData.getBytes(), -1);
        } catch (KeeperException e) {
            e.printStackTrace();
            logger.info("更新数据失败，发生KeeperException，path{}",path);
        } catch (InterruptedException e) {
            e.printStackTrace();
            logger.info("更新数据失败，发生InterruptedException，path{}",path);
        }
        logger.info("更新数据成功，更新前的数据为{}",oldData);
        return true;
    }

    /**
     * 删除指定节点
     * @param path
     * @return
     */
    public boolean deleteNode(String path){
        try {
            this.zk.delete(path,-1);
        } catch (InterruptedException e) {
            e.printStackTrace();
            logger.info("删除节点失败，发生InterruptedException，path{}",path);
        } catch (KeeperException e) {
            e.printStackTrace();
            logger.info("删除节点失败，发生KeeperException，path{}",path);
        }
        logger.info("删除节点成功，path{}",path);
        return true;
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        TestJavaApi api = new TestJavaApi();
        api.createSafeConnection();
        boolean isCreateNode = api.createPath("/aaa", "aaa");
        String data = api.getData("/aaa");
        System.out.println(isCreateNode+","+data);
        System.out.println("节点数据为："+data);
        api.close();
    }

}
